
interface EventObject{
    type:string;
    paras:any;
}
interface EventHandle{
    (e:EventObject):void;
}

class Event {

    private _handles:any={};
    private _onceHandles:any={};

    //----------------------------------------内部属性方法----------------------------------------

    //触发事件的函数
    private _dispatch(e:EventObject):void {
        let handles = this._handles[e.type];
        let nullIndexs:Array<number> = [];
        if (Array.isArray(handles)) {
            handles.forEach((handle, index) => {
                if (handle) {
                    handle(e);
                } else {
                    nullIndexs.push(index);
                }
            });
            for (let i = nullIndexs.length - 1; i > -1; i--) {
                handles.splice(nullIndexs[i], 1);
            }
            if (handles.length < 1) {
                delete this._handles[e.type];
            }
        }

        handles = this._onceHandles[e.type];
        if (Array.isArray(handles)) {
            handles.forEach((handle) => {
                if (handle) {
                    handle(e);
                }
            });
            delete this._onceHandles[e.type];
        }
    }

    public debug():void {
        console.log({...this._handles, ...this._onceHandles});
    }

    public addEventListener(eventType:string, handle:EventHandle):void {
        this._handles[eventType] = this._handles[eventType] || [];
        if (this._handles[eventType].indexOf(handle) === -1) {
            this._handles[eventType].push(handle);
        }
    }

    public addEventListenerOnce(eventType:string, handle:EventHandle) {
        this._onceHandles[eventType] = this._onceHandles[eventType] || [];
        if (this._onceHandles[eventType].indexOf(handle) === -1) {
            this._onceHandles[eventType].push(handle);
        }
    }

    public removeEventListener(eventType:string, handle:EventHandle):void {

        let handles = this._handles[eventType];
        let index = -1;
        if (handles) {
            index = handles.indexOf(handle);
            if (index !== -1) {
                handles[index] = null;
            }
        }

        handles = this._onceHandles[eventType];
        if (handles) {
            index = handles.indexOf(handle);
            if (index !== -1) {
                handles[index] = null;
            }
        }
    }

    public clear(eventType:string|undefined|null):void {
        if (eventType) {
            delete this._handles[eventType];
            delete this._onceHandles[eventType];
        } else {
            this._handles = {};
        }
    }

    public dispatchEvent(...events:Array<EventObject>):void {
        events.forEach((event) => {
            this._dispatch(event);
        });
    }

    public isContain(eventType:string|undefined|null):boolean {
        const handlesContain = (handles:Array<EventHandle>) => {
            if (handles) {
                for (let i = 0, len = handles.length; i < len; i++) {
                    if (handles[i]) {
                        return true;
                    }
                }
                return false;
            }
            return false;
        };
        if (eventType) {
            if (handlesContain(this._handles[eventType])) {
                return true;
            }
            return handlesContain(this._onceHandles[eventType]);
        }
        const mapContain = (handleMap:any) => {
            for (let key in handleMap) {
                let handles = handleMap[key];
                if (handles) {
                    for (let i = 0, len = handles.length; i < len; i++) {
                        if (handles[i]) {
                            return true;
                        }
                    }
                }
            }
            return false;
        };
        if (mapContain(this._handles)) {
            return true;
        }
        return mapContain(this._onceHandles);
    }
}

const EventCenter:Event=new Event();

export {Event,EventCenter};